home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 2: Applications
/
Linux Cubed Series 2 - Applications.iso
/
hamradio
/
tnos-2.000
/
tnos-2
/
lzhuf.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-22
|
36KB
|
1,276 lines
/* This STANDALONE variable doesn't work to build a Standalone LZHUF executable. */
#undef STANDALONE 1
/*
************************************************************
lzhuf.c
written by Haruyasu Yoshizaki 11/20/1988
some minor changes 4/6/1989
comments translated by Haruhiko Okumura 4/7/1989
************************************************************
*/
#include "ctype.h"
#ifndef STANDALONE
#include "global.h"
#include <time.h>
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LZHUF 1
#define mallocw malloc
#endif
#ifndef UNIX
#include <alloc.h>
#endif
#if defined(LZHUF) || defined(FBBCMP)
#include "proc.h"
#include "socket.h"
#include "timer.h"
#include "usock.h"
#include "netuser.h"
#include "session.h"
#include "lzhuf.h"
#undef DEBUG 1
#undef DEBUG2 1
#if !defined(_lint) && !defined(MSDOS)
static char rcsid[] OPTIONAL = "$Id: lzhuf.c,v 1.10 1996/06/22 18:20:37 root Exp root $";
#endif
#if defined(CATALOG) && !defined(STANDALONE)
#include "catalog.h"
#define CAT lzhuf_catalog
#define ErrorEncode __STR(0)
#define lostremote __STR(1)
#define ErrorDecode __STR(2)
#define Erroropening __STR(3)
#define ENCODEratio __STR(4)
#define DECODEratio __STR(5)
#else /* CATALOG */
static const char DFAR ErrorEncode[] = "FWDCMP: Error from Encode() rc = %d";
static const char DFAR lostremote[] = "FBBFWD: Lost the remote connection in recv_yapp()";
static const char DFAR ErrorDecode[] = "FWDCMP: Error from Decode() rc = %d";
static const char DFAR Erroropening[] = "FBBFWD: Error opening %s in %s\n";
static const char DFAR ENCODEratio[] = "FWDCMP: ENCODE: In: %-8ld Out: %-8ld (%ld%%)\n";
static const char DFAR DECODEratio[] = "FWDCMP: DECODE: In: %-8ld Out: %-8ld (%ld%%)\n";
#endif /* CATALOG */
static const char DFAR Encodestr[] = "Encode()";
static const char DFAR Decodestr[] = "Decode()";
#ifdef STANDALONE
#undef free
#undef malloc
#define tcmdprintf printf
int FBBtrace = 1;
#endif
void AllocDataBuffers(struct fwd *f) {
f->lzhuf = mallocw(sizeof(struct lzhufstruct));
#if 0
f->tmpBuffer = mallocw(260);
#endif
f->lzhuf->data_type = 0; /* 0 means not allocated yet. */
f->lzhuf->data = malloc(sizeof(struct lzhufdata));
if(f->lzhuf->data != NULLLZHUFDATA)
f->lzhuf->data_type = 2; /* 2 means big buffer + lower memory. */
if(f->lzhuf->data_type == 0) {
f->lzhuf->data_type = 1; /* 1 means small buffers + lower memory. */
f->lzhuf->dad = mallocw((N + 1) * sizeof(int));
f->lzhuf->lson = mallocw((N + 1) * sizeof(int));
f->lzhuf->rson = mallocw((N + 257) * sizeof(int));
f->lzhuf->text_buf = mallocw((N + F - 1) * sizeof(unsigned char));
f->lzhuf->freq = mallocw((T + 1) * sizeof(unsigned));
f->lzhuf->prnt = mallocw((T + N_CHAR) * sizeof(int));
f->lzhuf->son = mallocw((T) * sizeof(int));
} else {
/* point pointers to correct spot in large buffer. */
f->lzhuf->dad = f->lzhuf->data->dad;
f->lzhuf->rson = f->lzhuf->data->rson;
f->lzhuf->lson = f->lzhuf->data->lson;
f->lzhuf->text_buf = f->lzhuf->data->text_buf;
f->lzhuf->freq = f->lzhuf->data->freq;
f->lzhuf->prnt = f->lzhuf->data->prnt;
f->lzhuf->son = f->lzhuf->data->son;
}
f->lzhuf->codesize = 0;
f->lzhuf->getbuf = 0;
f->lzhuf->getlen = 0;
f->lzhuf->putbuf = 0;
f->lzhuf->putlen = 0;
f->lzhuf->code = 0;
f->lzhuf->len = 0;
}
void FreeDataBuffers(struct fwd *f) {
#if 0
free(f->tmpBuffer);
#endif
if(f->lzhuf->data_type == 1) {
/* Free lower memory blocks. */
free(f->lzhuf->dad);
free(f->lzhuf->lson);
free(f->lzhuf->rson);
free(f->lzhuf->text_buf);
free(f->lzhuf->freq);
free(f->lzhuf->prnt);
free(f->lzhuf->son);
} else
if(f->lzhuf->data_type == 2) {
/* Free lower memory block. */
free(f->lzhuf->data);
}
free(f->lzhuf);
f->lzhuf = NULLLZHUFSTRUCT;
}
int Encode (int, char *, char *,struct lzhufstruct *, int trace);
int Decode (int, char *, char *, struct lzhufstruct *, int addex, int trace);
int GetBit (struct lzhufstruct *);
unsigned short GetByte (struct lzhufstruct *);
void Putcode (struct lzhufstruct *, int, unsigned);
void EncodeEnd (struct lzhufstruct *);
int DecodeChar(struct lzhufstruct *);
void InitTree (struct lzhufstruct *);
void InsertNode(struct lzhufstruct *, int);
void StartHuff (struct lzhufstruct *);
void reconst (struct lzhufstruct *);
void update (struct lzhufstruct *, int);
void EncodeChar(struct lzhufstruct *, unsigned);
void EncodePosition(struct lzhufstruct *, unsigned);
int DecodePosition(struct lzhufstruct *);
void DeleteNode(struct lzhufstruct *, int);
int recvbuf (int,char *,unsigned);
/********** LZSS compression **********/
void InitTree(struct lzhufstruct *lzhuf) /* initialize trees */
{
int i;
for (i = N + 1; i <= N + 256; i++)
lzhuf->rson[i] = NIL; /* root */
for (i = 0; i < N; i++)
lzhuf->dad[i] = NIL; /* node */
}
void InsertNode(struct lzhufstruct *lzhuf, int r) /* insert to tree */
{
int i, p, cmp;
unsigned char *key;
unsigned c;
cmp = 1;
key = &lzhuf->text_buf[r];
p = N + 1 + key[0];
lzhuf->rson[r] = lzhuf->lson[r] = NIL;
lzhuf->match_length = 0;
for(;;) {
if(cmp >= 0) {
if(lzhuf->rson[p] != NIL)
p = lzhuf->rson[p];
else {
lzhuf->rson[p] = r;
lzhuf->dad[r] = p;
return;
}
} else {
if(lzhuf->lson[p] != NIL)
p = lzhuf->lson[p];
else {
lzhuf->lson[p] = r;
lzhuf->dad[r] = p;
return;
}
}
for(i = 1; i < F; i++)
if((cmp = key[i] - lzhuf->text_buf[p + i]) != 0)
break;
if(i > THRESHOLD) {
if(i > lzhuf->match_length) {
lzhuf->match_position = ((r - p) & (N - 1)) - 1;
if((lzhuf->match_length = i) >= F)
break;
}
if(i == lzhuf->match_length) {
if((c = ((r - p) & (N - 1)) - 1) < (unsigned)lzhuf->match_position) {
lzhuf->match_position = c;
}
}
}
}
lzhuf->dad[r] = lzhuf->dad[p];
lzhuf->lson[r] = lzhuf->lson[p];
lzhuf->rson[r] = lzhuf->rson[p];
lzhuf->dad[lzhuf->lson[p]] = r;
lzhuf->dad[lzhuf->rson[p]] = r;
if(lzhuf->rson[lzhuf->dad[p]] == p)
lzhuf->rson[lzhuf->dad[p]] = r;
else
lzhuf->lson[lzhuf->dad[p]] = r;
lzhuf->dad[p] = NIL; /* remove p */
}
void DeleteNode(struct lzhufstruct *lzhuf, int p) /* remove from tree */
{
int q;
if(lzhuf->dad[p] == NIL)
return; /* not registered */
if(lzhuf->rson[p] == NIL)
q = lzhuf->lson[p];
else
if(lzhuf->lson[p] == NIL)
q = lzhuf->rson[p];
else {
q = lzhuf->lson[p];
if(lzhuf->rson[q] != NIL) {
do {
q = lzhuf->rson[q];
} while (lzhuf->rson[q] != NIL);
lzhuf->rson[lzhuf->dad[q]] = lzhuf->lson[q];
lzhuf->dad[lzhuf->lson[q]] = lzhuf->dad[q];
lzhuf->lson[q] = lzhuf->lson[p];
lzhuf->dad[lzhuf->lson[p]] = q;
}
lzhuf->rson[q] = lzhuf->rson[p];
lzhuf->dad[lzhuf->rson[p]] = q;
}
lzhuf->dad[q] = lzhuf->dad[p];
if(lzhuf->rson[lzhuf->dad[p]] == p)
lzhuf->rson[lzhuf->dad[p]] = q;
else
lzhuf->lson[lzhuf->dad[p]] = q;
lzhuf->dad[p] = NIL;
}
/* Huffman coding */
/* table for encoding and decoding the upper 6 bits of position */
/* for encoding */
#define MAX_P_LEN 64
uchar p_len[MAX_P_LEN] = {
0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
};
uchar p_code[MAX_P_LEN] = {
0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
/* for decoding */
#define MAX_D_LEN 256
uchar d_code[MAX_D_LEN] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
};
uchar d_len[MAX_D_LEN] = {
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
};
int GetBit(struct lzhufstruct *lzhuf) /* get one bit */
{
register unsigned i;
register unsigned dx = lzhuf->getbuf;
register unsigned char glen = lzhuf->getlen;
while(glen <= 8) {
i = getc(lzhuf->iFile);
if ((int)i < 0)
i = 0;
dx |= i << (8 - glen);
glen += 8;
}
lzhuf->getbuf = dx << 1;
lzhuf->getlen = glen - 1;
return (dx & 0x8000) ? 1 : 0;
}
unsigned short GetByte(struct lzhufstruct *lzhuf) /* get one byte */
{
register unsigned i;
register unsigned dx = lzhuf->getbuf;
register unsigned char glen = lzhuf->getlen;
while(glen <= 8) {
i = getc(lzhuf->iFile);
if ((int)i < 0)
i = 0;
dx |= i << (8 - glen);
glen += 8;
}
lzhuf->getbuf = dx << 8;
lzhuf->getlen = glen - 8;
return (dx >> 8) & 0xff;
}
void Putcode(struct lzhufstruct *lzhuf, int l, unsigned c) /* output c bits of code */
{
lzhuf->putbuf |= c >> lzhuf->putlen;
if((lzhuf->putlen += l) >= 8) {
if(putc(lzhuf->putbuf >> 8, lzhuf->oFile) == EOF) {
return;
}
if((lzhuf->putlen -= 8) >= 8) {
if(putc(lzhuf->putbuf, lzhuf->oFile) == EOF) {
return;
}
lzhuf->codesize += 2;
lzhuf->putlen -= 8;
lzhuf->putbuf = c << (l - lzhuf->putlen);
} else {
lzhuf->putbuf <<= 8;
lzhuf->codesize++;
}
}
}
/* initialization of tree */
void StartHuff(struct lzhufstruct *lzhuf)
{
int i, j;
for(i = 0; i < N_CHAR; i++) {
lzhuf->freq[i] = 1;
lzhuf->son[i] = i + T;
lzhuf->prnt[i + T] = i;
}
i = 0; j = N_CHAR;
while(j <= R) {
lzhuf->freq[j] = lzhuf->freq[i] + lzhuf->freq[i + 1];
lzhuf->son[j] = i;
lzhuf->prnt[i] = lzhuf->prnt[i + 1] = j;
i += 2; j++;
}
lzhuf->freq[T] = 0xffff;
lzhuf->prnt[R] = 0;
lzhuf->putlen = lzhuf->getlen = 0;
lzhuf->putbuf = lzhuf->getbuf = 0;
}
/* reconstruction of tree */
void reconst(struct lzhufstruct *lzhuf)
{
int i, j, k;
unsigned first;
/* collect leaf nodes in the first half of the table */
/* and replace the freq by (freq + 1) / 2. */
j = 0;
for(i = 0; i < T; i++) {
if(lzhuf->son[i] >= T) {
lzhuf->freq[j] = (lzhuf->freq[i] + 1) / 2;
lzhuf->son[j] = lzhuf->son[i];
j++;
}
}
/* begin constructing tree by connecting sons */
for(i = 0, j = N_CHAR; j < T; i += 2, j++) {
k = i + 1;
first = lzhuf->freq[j] = lzhuf->freq[i] + lzhuf->freq[k];
for (k = j - 1; first < lzhuf->freq[k]; k--);
k++;
{ register unsigned *p, *e;
for (p = &lzhuf->freq[j], e = &lzhuf->freq[k]; p > e; p--)
p[0] = p[-1];
lzhuf->freq[k] = first;
}
{ register int *p, *e;
for (p = &lzhuf->son[j], e = &lzhuf->son[k]; p > e; p--)
p[0] = p[-1];
lzhuf->son[k] = i;
}
}
/* connect prnt */
for(i = 0; i < T; i++) {
if((k = lzhuf->son[i]) >= T) {
lzhuf->prnt[k] = i;
} else {
lzhuf->prnt[k] = lzhuf->prnt[k + 1] = i;
}
}
}
/* increment frequency of given code by one, and update tree */
void update(struct lzhufstruct *lzhuf, int c)
{
int i, j, k, l;
if(lzhuf->freq[R] == MAX_FREQ) {
reconst(lzhuf);
}
c = lzhuf->prnt[c + T];
do {
k = ++lzhuf->freq[c];
/* if the order is disturbed, exchange nodes */
if((unsigned)k > lzhuf->freq[l = c + 1]) {
while ((unsigned) k > lzhuf->freq[++l]);
l--;
lzhuf->freq[c] = lzhuf->freq[l];
lzhuf->freq[l] = k;
i = lzhuf->son[c];
lzhuf->prnt[i] = l;
if (i < T) lzhuf->prnt[i + 1] = l;
j = lzhuf->son[l];
lzhuf->son[l] = i;
lzhuf->prnt[j] = c;
if (j < T) lzhuf->prnt[j + 1] = c;
lzhuf->son[c] = j;
c = l;
}
} while ((c = lzhuf->prnt[c]) != 0); /* repeat up to root */
}
void EncodeChar(struct lzhufstruct *lzhuf, unsigned c)
{
unsigned i;
int j, k;
i = 0;
j = 0;
k = lzhuf->prnt[c + T];
/* travel from leaf to root */
do {
i >>= 1;
/* if node's address is odd-numbered, choose bigger brother node */
if (k & 1) i += 0x8000;
j++;
} while ((k = lzhuf->prnt[k]) != R);
Putcode(lzhuf, j, i);
lzhuf->code = i;
lzhuf->len = j;
update(lzhuf, c);
}
void EncodePosition(struct lzhufstruct *lzhuf, unsigned c)
{
unsigned i;
/* output upper 6 bits by table lookup */
i = c >> 6;
#ifdef DEBUG
if (i >= MAX_P_LEN)
tcmdprintf("Ah....FYI...you've just exceded the MAX_P_LEN variable ( %d ) with %d\n", MAX_P_LEN, i);
#endif
Putcode(lzhuf, p_len[i], (unsigned)p_code[i] << 8);
/* output lower 6 bits verbatim */
Putcode(lzhuf, 6, (c & 0x3f) << 10);
}
void EncodeEnd(struct lzhufstruct *lzhuf)
{
if(lzhuf->putlen) {
if(putc(lzhuf->putbuf >> 8, lzhuf->oFile) == EOF) {
return;
}
lzhuf->codesize++;
}
}
int DecodeChar(struct lzhufstruct *lzhuf)
{
unsigned c;
c = lzhuf->son[R];
/* travel from root to leaf, */
/* choosing the smaller child node (son[]) if the read bit is 0, */
/* the bigger (son[]+1} if 1 */
while (c < T) {
c += GetBit(lzhuf);
c = lzhuf->son[c];
}
c -= T;
update(lzhuf, c);
return c;
}
int DecodePosition(struct lzhufstruct *lzhuf)
{
unsigned j, c;
unsigned short i;
/* recover upper 6 bits from table */
i = GetByte(lzhuf);
#ifdef DEBUG
if (i >= MAX_D_LEN)
tcmdprintf("Ah....FYI...you've just exceded the MAX_D_LEN variable ( %u ) with %u\n", MAX_D_LEN, i);
#endif
c = (unsigned)d_code[i] << 6;
j = d_len[i];
/* read lower 6 bits verbatim */
j -= 2;
while (j--) {
i = (i << 1) + GetBit(lzhuf);
}
return c | (i & 0x3f);
}
/* compression */
int Encode(int usock OPTIONAL, char *txtFileName, char *binFileName, struct lzhufstruct *lzhuf, int trace)
{
int i, c, len, r, s, last_match_length;
unsigned long int filesize = 0;
#ifdef DEBUG
tcmdprintf("Encoding %s into %s\n", txtFileName, binFileName);
#endif
/* Open input and output files. */
if((lzhuf->iFile = fopen(txtFileName, "rb")) == NULLFILE) {
if (trace)
tcmdprintf(Erroropening, txtFileName, Encodestr);
return 0;
}
if((lzhuf->oFile = fopen(binFileName, "wb")) == NULLFILE) {
if (trace)
tcmdprintf(Erroropening, binFileName, Encodestr);
return 0;
}
fseek(lzhuf->iFile, 0L, 2);
filesize = ftell(lzhuf->iFile);
if(filesize == 0)
return 0;
/* output size of text */
if(fwrite(&filesize, sizeof(filesize), 1, lzhuf->oFile) < 1)
return 0;
rewind(lzhuf->iFile);
lzhuf->iFileSize = filesize;
filesize = 0; /* rewind and re-read */
StartHuff(lzhuf);
InitTree(lzhuf);
s = 0;
r = N - F;
for(i = s; i < r; i++)
lzhuf->text_buf[i] = ' ';
for(len = 0; len < F && (c = getc(lzhuf->iFile)) != EOF; len++)
lzhuf->text_buf[r + len] = c;
filesize = len;
for(i = 1; i <= F; i++)
InsertNode(lzhuf, r - i);
InsertNode(lzhuf, r);
do {
pwait(NULL);
if(lzhuf->match_length > len)
lzhuf->match_length = len;
if(lzhuf->match_length <= THRESHOLD) {
lzhuf->match_length = 1;
EncodeChar(lzhuf,lzhuf->text_buf[r]);
} else {
EncodeChar(lzhuf,255 - THRESHOLD + lzhuf->match_length);
EncodePosition(lzhuf,lzhuf->match_position);
}
last_match_length = lzhuf->match_length;
for(i = 0; i < last_match_length && (c = getc(lzhuf->iFile)) != EOF; i++) {
DeleteNode(lzhuf, s);
lzhuf->text_buf[s] = c;
if(s < F - 1)
lzhuf->text_buf[s + N] = c;
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
InsertNode(lzhuf, r);
}
while(i++ < last_match_length) {
DeleteNode(lzhuf, s);
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
if (--len) InsertNode(lzhuf, r);
}
} while (len > 0);
EncodeEnd(lzhuf);
fclose(lzhuf->iFile);
fclose(lzhuf->oFile);
if(lzhuf->iFileSize == 0)
lzhuf->iFileSize = 1;
if (trace)
tcmdprintf(ENCODEratio, lzhuf->iFileSize, lzhuf->codesize,
(100 - ((lzhuf->codesize*100) / lzhuf->iFileSize)));
return 1;
}
int Decode(int usock OPTIONAL, char *iFile, char *oFile, struct lzhufstruct *lzhuf, int addex, int trace)
{
int i = 0;
int j = 0;
int k = 0;
int r = 0;
int c = 0;
unsigned long int count = 0;
long int filesize = 0;
#ifdef DEBUG
tcmdprintf("Decoding %s into %s\n", iFile, oFile);
#endif
/* Open input and output files. */
if((lzhuf->iFile = fopen(iFile, "rb")) == NULLFILE) {
if (trace)
tcmdprintf(Erroropening, iFile, Decodestr);
return 0;
}
if ((lzhuf->oFile = fopen(oFile, "wb")) == NULLFILE) {
if (trace)
tcmdprintf (Erroropening, oFile, Decodestr);
return 0;
}
fseek(lzhuf->iFile, 0L, 2);
filesize = ftell(lzhuf->iFile);
if(filesize == 0)
return 0;
lzhuf->iFileSize = filesize;
rewind(lzhuf->iFile);
if(fread(&filesize, sizeof(filesize), 1, lzhuf->iFile) < 1)
return 0;
if(filesize == 0)
return 0;
StartHuff(lzhuf);
for(i = 0; i < N - F; i++)
lzhuf->text_buf[i] = ' ';
r = N - F;
for(count = 0; count < (unsigned long)filesize; ) {
pwait(NULL);
c = DecodeChar(lzhuf);
if(c < 256) {
if(putc(c, lzhuf->oFile) == EOF) {
return 0;
}
lzhuf->text_buf[r++] = c;
r &= (N - 1);
count++;
} else {
i = (r - DecodePosition(lzhuf) - 1) & (N - 1);
j = c - 255 + THRESHOLD;
for(k = 0; k < j; k++) {
c = lzhuf->text_buf[(i + k) & (N - 1)];
if(putc(c, lzhuf->oFile) == EOF) {
return 0;
}
lzhuf->text_buf[r++] = c;
r &= (N - 1);
count++;
}
}
}
#ifndef STANDALONE
if (addex)
/* This terminates a note. */
fputs("\n/EX\n",lzhuf->oFile);
#endif
fclose(lzhuf->iFile);
fclose(lzhuf->oFile);
if(count == 0)
count = 1;
if (trace)
tcmdprintf (DECODEratio, lzhuf->iFileSize, count,
(100 - ((lzhuf->iFileSize*100) / count)));
return 1;
}
#ifndef STANDALONE
int send_yapp(struct fwd *f, char *txtFileName, char *subj) {
#define SLEN 79 /* Maximum subject */
/* filename length. */
int oldmode; /* Socket Mode holder. */
#ifdef DEBUG2
FILE *debug;
#endif
char *buffer; /* buffer data. */
int buffer_len; /* buffer Length. */
int x; /* misc counter. */
int cnt; /* misc counter. */
int rc;
int Error;
int usock;
short b_checksum; /* buffer checksum. */
short f_checksum; /* file checksum. */
FILE *binFile;
char binFileName[80];
/* Debug info. */
#ifdef DEBUG2
if (((debug = fopen(tmpnam(NULL),"wb")) == NULLFILE)) {
printf("Error opening input file.\n");
return 0;
}
#endif
/* User socket */
usock = f->m->user;
/* Encode code. */
tmpnam(binFileName);
Error = FALSE;
pwait(NULL);
AllocDataBuffers(f);
rc = Encode(usock, txtFileName, binFileName, f->lzhuf, FBBtrace);
FreeDataBuffers(f);
pwait(NULL);
if(!rc) {
if (FBBtrace)
tcmdprintf (ErrorEncode, rc);
log(f->m->user, ErrorEncode, rc);
Error = TRUE;
unlink(binFileName); /* just in case */
}
unlink(txtFileName);
if(Error)
return 0;
/* open the compressed data file. */
/* Now... we're going to read from the file and close it when we exit. */
/* Open the input file. */
binFile = fopen(binFileName, "rb");
/* Debug info. */
#ifdef DEBUG
tcmdprintf("we opened %s for input.\n", f->oFile);
#endif
/* Grab some space. Largest YAPP packet is 250+ bytes. */
f->tmpBuffer = mallocw(260);
buffer = f->tmpBuffer;
/* Set the socket to Binary mode since we'll be sending Binary data. */
oldmode = sockmode(usock,SOCK_BINARY);
/* Send the subject buffer
The buffer is setup as follows:
Pos Data
1 SOH
2 Length of entire buffer ( 8 bytes + strlen(subject) )
3 Null terminated Subject string.
x Null terminated '0' string.
*/
/* Make sure that the subject strlen() is equal to or less than SLEN */
x = strlen(subj);
if (x >= SLEN) {
x = SLEN;
subj[SLEN] = '\0';
}
/* length of subject + NULL + length of " 0" + NULL */
buffer_len = x + 1 + 6 + 1;
/* Build the buffer. */
buffer[0] = SOH; /* buffer_Type */
buffer[1] = buffer_len; /* buffer_Len */
strcpy(&buffer[2], subj); /* Subject info. */
strcpy(&buffer[x+3], " 0"); /* Always 0 for FBB Messages. */
/* Now we can send it. */
/* buffer_len + 2 ( for the first two bytes. */
usputbuf(usock, buffer, buffer_len+2);
#ifdef DEBUG2
fwrite(buffer, buffer_len+2, 1, debug);
#endif
/* Send the data buffers. */
f_checksum = 0;
/* fill buffer with data. Bytes 0 and 1 are reserved. */
while ((x = fread(&buffer[2], 1, 250, binFile)) > 0) {
/* prepare the buffer. */
buffer[0] = STX; /* buffer_Type */
buffer[1] = x; /* buffer_Len */
b_checksum = 0;
for (cnt=0;cnt<x;cnt++) {
b_checksum += buffer[2 + cnt]; /* buffer checksum. */
}
#if 0 /* must be for FBB 4.15C ?? */
buffer[x + 2] = ((-b_checksum) & 0xff); /* Store b_checksum. */
#endif
/* and send it. */
usputbuf(usock, buffer, (x + 2));
#ifdef DEBUG2
fwrite(buffer, x + 2, 1, debug);
#endif
f_checksum += b_checksum;
} /* endwhile */
/* Send the EOT */
/* Prepare the buffer. */
buffer[0] = EOT; /* buffer_Type */
buffer[1] = ((-f_checksum) & 0xff); /* Checksum. */
/* and send it. */
usputbuf(usock, buffer, 2);
#ifdef DEBUG2
fwrite(buffer, 2, 1, debug);
#endif
/* Terminate. */
fclose(binFile);
/* Delete binFileName */
unlink (binFileName);
#ifdef DEBUG2
fclose(debug);
#endif
free (f->tmpBuffer);
/* Set the socket back to it's orginal mode. */
sockmode(usock,oldmode);
return 1;
}
int recv_yapp(struct fwd *f) {
int recvcnt;
int packet_type;
unsigned int packet_size;
char packet_data[258];
int GetSubject;
int NoteDone;
int NoteError;
unsigned int rx_checksumctr;
unsigned int rx_checksum;
int rc;
int oldmode; /* Socket Mode holder. */
FILE *iFile = NULLFILE;
int usock;
/* User socket */
usock = f->m->user;
/* Set the socket to Binary mode since we'll be sending Binary data. */
oldmode = sockmode(usock,SOCK_BINARY);
GetSubject = TRUE;
NoteDone = FALSE;
NoteError = FALSE;
rx_checksum = 0;
while(!NoteDone) {
/* Get the data packets. */
packet_type = recvchar(usock);
if (GetSubject) {
if (packet_type != SOH) {
FBBerror (0, usock, f->m);
NoteDone = NoteError = TRUE;
continue;
}
} else
if ((packet_type != STX) && (packet_type != EOT)) {
/* Get the packet size. */
packet_size = recvchar(usock);
FBBerror (3, usock, f->m);
NoteDone = NoteError = TRUE;
continue;
}
/* Get the packet size. */
packet_size = recvchar(usock);
if (!packet_size)
packet_size=256; /* 0x00 always means 256 */
if (packet_type == SOH) {
/* This is the subject. Reset the flag so we don't */
/* come here again. */
GetSubject = FALSE;
/* Open the output file. */
if (iFile == NULLFILE) /* shouldn't be needed, but just in case */
iFile = fopen(f->iFile, "wb");
/* This is a subject packet (with the offset hiding behind it). */
recvcnt = recvbuf(usock, &packet_data[0], packet_size+1);
/* we have now read the subject (which we'll use) and the
offset (which we are assuming to be zero), which we ignore */
if(recvcnt == -1) {
if (FBBtrace) {
tcmdprintf (lostremote);
tcmdprintf ("\n");
}
log(f->m->user, lostremote);
/* We've lost the connection.... */
NoteDone = NoteError = TRUE;
} else
f->m->subject = strdup(packet_data);
} /* endif */
else
if (packet_type == STX) {
/* Validate the packet */
/* and write it to the file. */
recvcnt = recvbuf(usock, &packet_data[0], packet_size+1);
if(recvcnt == -1) {
if (FBBtrace) {
tcmdprintf (lostremote);
tcmdprintf ("\n");
}
log(f->m->user, lostremote);
/* We've lost the connection.... */
NoteDone = NoteError = TRUE;
} else {
/* Write to disk */
fwrite(packet_data, recvcnt, 1, iFile);
/* add the data to the rx_checksum count. */
for(rx_checksumctr=0;rx_checksumctr<packet_size;rx_checksumctr++) {
rx_checksum += (unsigned char) packet_data[rx_checksumctr];
}
}
} /* endif */
else
if (packet_type == EOT) {
/* Close the file. */
/* Validate the Checksum. */
/* erase the file if Checksum fails.*/
/* Get ready to read next message. */
if (packet_size == 256)
packet_size = 0;
if (packet_size != ((-rx_checksum) & 0xff)) {
NoteDone = NoteError = TRUE;
usputs (usock, "*** CHECKSUM ERROR\n");
if (FBBtrace)
tcmdprintf ("FBBCMP: Checksum Error in message data\n");
log (f->m->user, "Checksum Error in message data");
} else if (FBBtrace)
tcmdprintf ("FBBCMP: YAPP Message Checksum verified\n");
/* Close the data file. */
fclose(iFile);
iFile = NULLFILE;
/* We're done with this message. Return. */
NoteDone = TRUE;
} /* endif */
} /* End while !NoteDone */
if(!NoteError) {
pwait(NULL);
AllocDataBuffers(f);
rc = Decode(usock, f->iFile, f->oFile, f->lzhuf, 1, FBBtrace);
FreeDataBuffers(f);
pwait(NULL);
if(!rc) {
if (FBBtrace)
tcmdprintf (ErrorDecode, rc);
log(f->m->user, ErrorDecode, rc);
NoteError = TRUE;
}
}
if (iFile != NULLFILE)
fclose(iFile);
/* delete compressed file. */
unlink(f->iFile);
/* Set the socket back to it's orginal mode. */
sockmode(usock,oldmode);
if(!NoteError)
return 1;
else
return 0;
}
/* Receive a buffer from a socket, returning # chars read.
*/
int recvbuf(int s, char *buf, unsigned len) {
int c;
int cnt = 0;
while(len-- > 1){
if((c = recvchar(s)) == EOF){
cnt = -1;
break;
}
if(buf != NULLCHAR)
*buf++ = c;
cnt++;
}
return cnt;
}
#endif
#ifdef XFWD
int send_lzhuf (struct fwd *f, char *txtFileName)
{
int oldmode; /* Socket Mode holder. */
int rc, c;
int Error;
int usock;
FILE *binFile;
char binFileName[80];
int16 newchecksum = 0;
/* User socket */
usock = f->m->user;
/* Encode code. */
tmpnam (binFileName);
Error = FALSE;
pwait (NULL);
AllocDataBuffers (f);
rc = Encode (usock, txtFileName, binFileName, f->lzhuf, Xtrace);
FreeDataBuffers (f);
pwait(NULL);
if (!rc) {
if (Xtrace)
tcmdprintf (ErrorEncode, rc);
log (f->m->user, ErrorEncode, rc);
Error = TRUE;
unlink (binFileName); /* just in case */
}
unlink (txtFileName);
if (Error) {
tprintf ("SS 0\n");
return 0;
}
/* open the compressed data file. */
/* Now... we're going to read from the file and close it when we exit. */
pwait (NULL);
/* Open the input file. */
binFile = fopen (binFileName, "rb");
pwait (NULL);
/* Calculate checksum */
while ((c = fgetc (binFile)) != EOF)
newchecksum += c;
rewind (binFile);
pwait (NULL);
tprintf ("SS %ld %u\n", filelength (fileno(binFile)), newchecksum);
if (Xtrace)
tcmdprintf ("XFWD: Sending 'SS %ld %u'\n", filelength (fileno(binFile)), newchecksum);
/* Set the socket to Binary mode since we'll be sending Binary data. */
oldmode = sockmode (usock, SOCK_BINARY);
while ((c = fgetc (binFile)) != EOF)
tputc (c);
/* Terminate. */
fclose (binFile);
/* Delete binFileName */
unlink (binFileName);
/* Set the socket back to it's orginal mode. */
sockmode (usock, oldmode);
return 1;
}
int recv_lzhuf (struct fwd *f, int msgsize, int16 *newchecksum)
{
int c;
int Error = FALSE;
int rc;
int oldmode; /* Socket Mode holder. */
FILE *iFile = NULLFILE;
int usock;
*newchecksum = 0;
/* User socket */
usock = f->m->user;
/* Set the socket to Binary mode since we'll be sending Binary data. */
oldmode = sockmode (usock, SOCK_BINARY);
iFile = fopen(f->iFile, "wb");
while(msgsize--) {
/* Get the data. */
c = recvchar (usock);
*newchecksum += c;
fputc (c, iFile);
}
fclose (iFile);
AllocDataBuffers (f);
rc = Decode (usock, f->iFile, f->oFile, f->lzhuf, 0, Xtrace);
FreeDataBuffers (f);
if (!rc) {
if (Xtrace)
tcmdprintf (ErrorDecode, rc);
log (f->m->user, ErrorDecode, rc);
Error = TRUE;
}
/* delete compressed file. */
unlink (f->iFile);
pwait (NULL);
/* Set the socket back to it's orginal mode. */
sockmode (usock, oldmode);
if (!Error)
return 1;
else
return 0;
}
#endif
#ifdef STANDALONE
int pwait (volatile void *event)
{
}
main(argc, argv, envp)
int argc;
char *argv[];
char *envp[];
{
struct fwd f;
AllocDataBuffers (&f);
if (argv[1][0] == 'd') {
Decode(0, argv[2], argv[3], f.lzhuf, 0, FBBtrace);
} else {
Encode(0, argv[2], argv[3], f.lzhuf, FBBtrace);
} /* endif */
}
#endif
#endif